/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pt.ua.miect.sd.simuladorpesca.conns;

import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import pt.ua.miect.sd.simuladorpesca.config.NodeService;

/**
 * Implementation of a Logical Clock
 * @author PedroA
 */
public class VectorClock {

    private ConcurrentHashMap<String, Integer> clocks;
    private String ourKey;

    /***
     * Constructor
     * @param key - indentifier to used on this counter 
     */
    public VectorClock(String key) {
        clocks = new ConcurrentHashMap<String, Integer>();
        clocks.put(key, 0);
        ourKey = key;
    }

     /***
     * Constructor
     * @param key - indentifier to used on this counter
     */
    public VectorClock(NodeService service) {
        String key = "";
        switch(service)
        {
            case Server:
                key = "H";
                break;
            case BoatControler:
                key = "M";
                break;
            case Boats:
                key = "B";
                break;
            case FishSchools:
                key = "F";
                break;
           case FishControler:
                key = "S";
                break;
            case Companies:
                key = "O";

        }
        clocks = new ConcurrentHashMap<String, Integer>();
        clocks.put(key, 0);
        ourKey = key;
    }

    /**
     * Increments the internal counter
     */
    public void increment() {
        Integer val = clocks.get(ourKey);
        val++;
        clocks.replace(ourKey, val);
    }

    /**
     * Gets all Keys that have associated clock
     * @return returns enumeration with keys
     */
    public Enumeration<String> getKeys() {
        return clocks.keys();
    }

    /**
     * Gets the value of one of the clocks
     * @param key of the clock to
     * @return
     */
    public Integer getClockValue(String key) {
        return clocks.get(key);
    }

    /**
     * Syncs this vector clock with another
     * @param other other vector clock
     */
    public void sync(VectorClock other) {
        Enumeration<String> keys = other.getKeys();
        while (keys.hasMoreElements()) {
            String otherKey = keys.nextElement();
            if (otherKey.equals(ourKey)) {
                continue;
            }

            if (clocks.containsKey(otherKey)) {
                //update value if higher then current
                Integer otherValue = other.getClockValue(otherKey);
                if (otherValue > clocks.get(otherKey)) {
                    clocks.replace(otherKey, otherValue);
                }
            } else {
                //add new clock
                clocks.put(otherKey, other.getClockValue(otherKey));
            }

        }
    }

     /**
     * Syncs this vector clock with another
     * @param other other vector clock
     */
    public void sync(String clockString) {
       Pattern pat = Pattern.compile("([A-Z]+)(\\d+)");
       Matcher matches = pat.matcher(clockString);
       if (matches.groupCount() > 0)
       {
           matches.
       }



        Enumeration<String> keys = other.getKeys();
        while (keys.hasMoreElements()) {
            String otherKey = keys.nextElement();
            if (otherKey.equals(ourKey)) {
                continue;
            }

            if (clocks.containsKey(otherKey)) {
                //update value if higher then current
                Integer otherValue = other.getClockValue(otherKey);
                if (otherValue > clocks.get(otherKey)) {
                    clocks.replace(otherKey, otherValue);
                }
            } else {
                //add new clock
                clocks.put(otherKey, other.getClockValue(otherKey));
            }

        }
    }



    /**
     * Returns a String containing the currect vector clock value
     * @return Vector clock value
     */
    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        Enumeration<String> keys = clocks.keys();
        while (keys.hasMoreElements())
        {
            String key = keys.nextElement();
            sb.append(key);
            sb.append(clocks.get(key));
        }
        return sb.toString();
    }



}
